package cy.jsonview.code;

import java.awt.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.swing.ImageIcon;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Tool {
	

	
	/**
	 * 将JsonObject数据载入到树
	 * @param jobj
	 * @param treeNode
	 */
	public static void analyzeJsonObject(JSONObject jobj, DefaultMutableTreeNode treeNode) {
        if (jobj.isEmpty()) {
            return;
        }
        

//        LinkedHashMap<String, String> jsonMap = JSON.parseObject(jsonStr, new TypeReference<LinkedHashMap<String, String>>() {
//        });
        
        // 使用这个map可以保持原来的数据顺序不变
        LinkedHashMap<String, Object> jsonMap =new LinkedHashMap<>();
        
//        TreeMap<String,Object> jsonMap = new TreeMap<>();
        for(Map.Entry<String, Object> entry : jobj.entrySet()){
            Object key = entry.getKey();
            jsonMap.put(key.toString(),entry.getValue());
        }
//
//        List<String> keyList = new ArrayList<String>();
//        Iterator<String> itkey = jobj.keySet().iterator();
//        while (itkey.hasNext()) {
//            keyList.add(itkey.next());
//        }
//        Collections.sort(keyList);
        for (Map.Entry<String, Object> entry : jsonMap.entrySet()) {
            //Object obj = jobj.get(key);
            String key = entry.getKey();
            Object obj = entry.getValue();
            if (obj instanceof JSONObject) {
                DefaultMutableTreeNode node = Kit.objNode(key);
                analyzeJsonObject((JSONObject) obj, node);
                treeNode.add(node);
            } else if (obj instanceof JSONArray) {
                analyzeJsonArray((JSONArray) obj, treeNode, key);
            } else if (obj instanceof String) {
                treeNode.add(Kit.strNode(key, (String) obj));
            } else if (obj instanceof Number) {
                treeNode.add(Kit.numNode(key, obj.toString()));
            } else if (obj instanceof Boolean) {
                treeNode.add(Kit.boolNode(key, (Boolean) obj));
            } else if (obj == null) {
                treeNode.add(Kit.nullNode(key));
            }
        }
        
        String jsonText = JSON.toJSONString(jobj, SerializerFeature.WriteMapNullValue, SerializerFeature.PrettyFormat);
        System.out.print(jsonText);
    }
	
	/**
	 * 将JsonArray数据载入到树
	 * @param jarr
	 * @param rootNode
	 * @param key
	 */
    public static void analyzeJsonArray(JSONArray jarr, DefaultMutableTreeNode rootNode, String key) {
    	int index = 0;
        DefaultMutableTreeNode topNode = Kit.arrNode(key);
        for (Iterator it = jarr.iterator(); it.hasNext(); ) {
            Object el = it.next();
            if (el instanceof JSONObject) {
                DefaultMutableTreeNode childNode = Kit.objNode(index);
                analyzeJsonObject((JSONObject) el, childNode);
                topNode.add(childNode);
            } else if (el instanceof JSONArray) {
                analyzeJsonArray((JSONArray) el, topNode, Kit.fkey(index));
            } else if (el instanceof String) {
                topNode.add(Kit.strNode(Kit.fkey(index), el.toString()));
            } else if (el instanceof Number) {
                topNode.add(Kit.numNode(Kit.fkey(index), el.toString()));
            } else if (el instanceof Boolean) {
                topNode.add(Kit.boolNode(Kit.fkey(index), (Boolean) el));
            } else if (el == null) {
                topNode.add(Kit.nullNode(Kit.fkey(index)));
            }
            ++index;
        }
        rootNode.add(topNode);
    }

    
    /**
     * 
     * @param json
     * @param model,1表示顺序，2表示倒序
     * @return
     */
    public static JSONObject getSortJson(JSONObject json,int model) {
        if (Objects.isNull(json)) {
            return new JSONObject();
        }
        
        SortedMap<String, Object> map;
        if(model==2) {
        	map = new TreeMap<>( Comparator.reverseOrder());
        	
        }else{
        	map = new TreeMap<>();
        }
      
      
        
        Set<String> keySet = json.keySet();
       

        for (String key:keySet) {
            Object value = json.get(key);
            if (Objects.nonNull(value) && value instanceof JSONArray) {
                JSONArray array = json.getJSONArray(key);
                JSONArray jsonArray = new JSONArray(new LinkedList<>());
                for (int i=0;i<array.size();i++) {
                    JSONObject sortJson = getSortJson(array.getJSONObject(i),model);
                    jsonArray.add(sortJson);
                }
                map.put(key, jsonArray);
            } else if (Objects.nonNull(value) && value instanceof JSONObject) {
                JSONObject sortJson = getSortJson(json.getJSONObject(key),model);
                map.put(key, sortJson);
            } else {
                map.put(key, value);
            }
        }
        return new JSONObject(map);
    }
    

    /**
     * 
     * @param json
     * @param model,1表示顺序，2表示倒序
     * @return
     */
    public static JSONArray getSortJson(JSONArray json,int model) {
    	//存放排序结果json数组
        JSONArray sortedJsonArray = new JSONArray();
        //用于排序的list
        List<JSONObject> jsonValues = new ArrayList<JSONObject>();
        //将参数json数组每一项取出，放入list
        for (int i = 0; i < json.size(); i++) {
          jsonValues.add(json.getJSONObject(i));
        }
        
      //将排序后结果放入结果jsonArray
        for (int i = 0; i < json.size(); i++) {
          sortedJsonArray.add(getSortJson(jsonValues.get(i),model));
        }
        return sortedJsonArray;
  
    }
    
    /**
	 * 
	 * @param tree
	 * @param nodePath：指定节点路径
	 * @param expand,为true就是展开指定节点，为false就是收起指定节点
	 */
	public static void expandItem(JTree tree, TreePath nodePath, boolean expand) { 

		if (expand) { 
		tree.expandPath(nodePath); 
		} else { 
		tree.collapsePath(nodePath); 
		} 
		}

	/**
	 * 设置树形区域配置,图标、字体
	 * @param tree
	 */
    public static void setNodeParameter(JTree tree,String baseResPath) {
        tree.setCellRenderer(new DefaultTreeCellRenderer() {
            @Override
            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
                super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
                setFont(Common.TREE_AREA_FONT);
//                setRowHeight(20);//每个节点的高度相同且为20像素
//                setRowHeight(0);//每个节点的高度根据实际情况而定
//                this.setTextNonSelectionColor(Common.TREE_TEXT_COLOR);//用这个方法设置文字颜色，被选中时，文字会变白色  
                setForeground(Common.TREE_TEXT_COLOR);// 设置文字的颜色
                setBackgroundSelectionColor(Common.TREE_BACKGROUND_SELECTION_COLOR);// 设置选中时的背景色
                setBackgroundNonSelectionColor(Common.TREE_BACKGROUND_NON_SELECTION_COLOR);// 设置没选中时的背景色
                
               
                
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                String tmp = node.toString();
                ClassLoader classLoader = getClass().getClassLoader();
                ImageIcon icon;
                if (tmp.startsWith(Kit.sArr)) {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "a.gif"));
                    setForeground(Common.TREE_OBJECT_COLOR);
                    setFont(Common.TREE_OBJECT_FONT);
                } else if (tmp.startsWith(Kit.sStr)) {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "str2.png"));
                    setForeground(Common.TREE_STR_COLOR);
                    setFont(Common.TREE_AREA_FONT);
                } else if (tmp.startsWith(Kit.sObj)) {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "null.png"));
                    setForeground(Common.TREE_OBJECT_COLOR);
                    setFont(Common.TREE_OBJECT_FONT);
                } else if (tmp.startsWith(Kit.sNum)) {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "number2.png"));
                    setForeground(Common.TREE_NUMBER_COLOR);
                    setFont(Common.TREE_AREA_FONT);
                } else if (tmp.startsWith(Kit.sNull)) {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "null2.png"));
                    setForeground(Common.TREE_NULL_COLOR);
                    setFont(Common.TREE_AREA_FONT);
                } else if (tmp.startsWith(Kit.sBool)) {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "boolean2.png"));
                    setForeground(Common.TREE_BOOLEAN_COLOR);
                    setFont(Common.TREE_AREA_FONT);
                } else {
                    icon = new ImageIcon(classLoader.getResource(baseResPath + "default2.png"));
                    setFont(Common.TREE_AREA_FONT);
                }
                this.setIcon(icon);
                this.setText(tmp.substring(2));
                
                
                
                return this;
                
                
            }

        });
    }
	
	/**
	 * 
	 * @param tree
	 * @param parent
	 * @param expand,为true就是展开树，为false就是收起树
	 * 
	 */
	public static void expandAll(JTree tree, TreePath parent, boolean expand) { 
		TreeNode node = (TreeNode) parent.getLastPathComponent(); 

		if (node.getChildCount() >= 0) { 
		for (Enumeration e = node.children(); e.hasMoreElements();) { 
		TreeNode n = (TreeNode) e.nextElement(); 
		TreePath path = parent.pathByAddingChild(n); 
		expandAll(tree, path, expand); 

			} 
		} 
		if (expand) { 
		tree.expandPath(parent); 
		} else { 
		tree.collapsePath(parent); 
		} 
	}


	/**
	 * 将unicode码转化成字符串
	 * @author shuai.ding
	 * @param unicode
	 * @return
	 */
	public static String unicode2String(String unicode) {
		if (StringUtils.isBlank(unicode)) {
			return null;
		}
 
		StringBuilder sb = new StringBuilder();
		int i = -1;
		int pos = 0;
 
		while ((i = unicode.indexOf("\\u", pos)) != -1) {
			sb.append(unicode.substring(pos, i));
			if (i + 5 < unicode.length()) {
				pos = i + 6;
				sb.append((char) Integer.parseInt(unicode.substring(i + 2, i + 6), 16));
			}
		}
		//如果pos位置后，有非中文字符，直接添加
		sb.append(unicode.substring(pos));
 
		return sb.toString();
	}

	
	
	/**
	 * 将字符串转化成unicode码
	 * @author shuai.ding
	 * @param string
	 * @return
	 */
	public static String string2Unicode(String string) {
 
		if (StringUtils.isBlank(string)) {
			return null;
		}
 
		char[] bytes = string.toCharArray();
		StringBuffer unicode = new StringBuffer();
		for (int i = 0; i < bytes.length; i++) {
			char c = bytes[i];
 
			// 标准ASCII范围内的字符，直接输出
			if (c >= 0 && c <= 127) {
				unicode.append(c);
				continue;
			}
			String hexString = Integer.toHexString(bytes[i]);
 
			unicode.append("\\u");
 
			// 不够四位进行补0操作
			if (hexString.length() < 4) {
				unicode.append("0000".substring(hexString.length(), 4));
			}
			unicode.append(hexString);
		}
		return unicode.toString();
	}

	/**
	 * 处理无关字符，增强xml兼容性
	 * @param xml
	 * @param addDefault,是否对不规范xml，加<all>...</all>包裹字符串
	 * @return
	 */
	public static String formatXml(String xml,boolean addDefault) {
		xml=xml.replaceAll("<\\?xml version=\\\"1\\.0\\\" encoding=\\\"UTF-8\\\"\\?>", "");
		
//		String pattern1 = "<\\?xml version=\\\"1\\.0\\\" encoding=\\\"UTF-8\\\"\\?>";
//		Pattern r1 = Pattern.compile(pattern1);
//		Matcher m1 = r1.matcher(xml);
//		xml=m1.replaceAll("");
		
//		System.out.println("替换后的: " + xml);
		
		xml=xml.trim();
		xml=xml.replaceAll("\n", "");
		
		if(addDefault) {
			String pattern = ".*?<(.*?)>.*</(.*)>.*";
			Pattern r = Pattern.compile(pattern);
			Matcher m = r.matcher(xml);
			
			if (m.find( )) {
//				System.out.println("Found value: " + m.group(0) );
//				System.out.println("Found value: " + m.group(1) );
//				System.out.println("Found value: " + m.group(2) );
				if(!m.group(1).equals(m.group(2))) {
					xml="<default>"+xml+"</default>";
//					System.out.println(xml );
				}
			}
		}
	    return xml;
	}
    
    
}
